package multimedia.view;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;

import multimedia.controller.EncodingController;
import multimedia.model.ModifiedImage;
import javax.swing.SwingConstants;

public class EncodingGui
{

    private JFrame phase2Frame;
    private JTextField pathTextField;
    private JButton browseButton;
    private JButton generateFileButton;
    private JButton decodeFileButton;
    private JTabbedPane codingTabbedPane;
    private final ButtonGroup predictiveCodingButtonGroup = new ButtonGroup();
    private final ButtonGroup quantizationButtonGroup = new ButtonGroup();
    private final ButtonGroup encodingButtonGroup = new ButtonGroup();
    private final ButtonGroup colorspaceButtonGroup = new ButtonGroup();
    private String[] actionCommandStrings =
        { "0", "1", "2", "3", "4", "5", "6", "7", "8" };
    private JTextField[] quantizationParameters = new JTextField[]{ new JTextField("0"),
                                                                    new JTextField("0"),
                                                                    new JTextField("0"),
                                                                    new JTextField("0.0")};
    private JTextField distortedFileField;
    private JButton distortedBrowseButton;
    private JLabel distortionLabel;

    /**
     * Launch the application.
     */
    public static void main( String[] args )
    {
        EventQueue.invokeLater(new Runnable() {
            public void run()
            {
                try
                {
                    EncodingGui window = new EncodingGui();
                    ModifiedImage model = new ModifiedImage();
                    @SuppressWarnings("unused")
                    EncodingController controller = new EncodingController(window, model);

                    window.phase2Frame.setVisible(true);
                } catch ( Exception e )
                {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public EncodingGui()
    {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize()
    {
        phase2Frame = new JFrame();
        phase2Frame.setResizable(false);
        phase2Frame.setTitle("Phase #2");
        phase2Frame.setBounds(100, 100, 735, 312);
        phase2Frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JRadioButton[] predictiveCodingButtons = new JRadioButton[9];
        JRadioButton[] quantizationButtons = new JRadioButton[3];
        JRadioButton[] encodingButtons = new JRadioButton[4];
        
        JRadioButton[] colorspaceButtons = new JRadioButton[]
            { new JRadioButton("RGB"), new JRadioButton("YIQ") };
        colorspaceButtons[0].setActionCommand("RGB");
        colorspaceButtonGroup.add(colorspaceButtons[0]);
        colorspaceButtons[1].setActionCommand("YIQ");
        colorspaceButtonGroup.add(colorspaceButtons[1]);

        JPanel quantizationPanel = new JPanel();
        JPanel qBinsPanel = new JPanel();
        JPanel predictiveCodingPanel = new JPanel();
        JPanel encodingPanel = new JPanel();

        predictiveCodingButtons[0] = new JRadioButton("No PC");
        predictiveCodingButtons[0].setActionCommand(actionCommandStrings[0]);
        predictiveCodingButtonGroup.add(predictiveCodingButtons[0]);

        for ( int i = 1; i < predictiveCodingButtons.length; i++ )
        {
            predictiveCodingButtons[i] = new JRadioButton("P" + i);
            predictiveCodingButtons[i].setActionCommand(actionCommandStrings[i]);
            predictiveCodingButtonGroup.add(predictiveCodingButtons[i]);
            predictiveCodingPanel.add(predictiveCodingButtons[i]);
        }

        quantizationButtons[0] = new JRadioButton("No quantization");
        quantizationButtons[1] = new JRadioButton("Uniform");
        quantizationButtons[2] = new JRadioButton("Non-Uniform");

        for ( int i = 0; i < quantizationButtons.length; i++ )
        {
            quantizationButtons[i].setActionCommand(actionCommandStrings[i]);
            quantizationButtonGroup.add(quantizationButtons[i]);
            quantizationPanel.add(quantizationButtons[i]);
        }

        encodingButtons[0] = new JRadioButton("No encoding");
        encodingButtons[1] = new JRadioButton("Huffman");
        encodingButtons[2] = new JRadioButton("Adaptive Huff.");
        encodingButtons[3] = new JRadioButton("LZW");

        for ( int i = 0; i < encodingButtons.length; i++ )
        {
            encodingButtons[i].setActionCommand(actionCommandStrings[i]);
            encodingButtonGroup.add(encodingButtons[i]);
            encodingPanel.add(encodingButtons[i]);
        }
        
        JLabel[] quantizationLabels = { new JLabel("N\u2081"), new JLabel("N\u2082"), new JLabel("N\u2083"), new JLabel("\u03B1") }; 
        for( int i = 0; i < quantizationLabels.length; i++ )
        {
            final JTextField currentTextField = quantizationParameters[i];
            // Adding focus listeners
            currentTextField.addFocusListener( new java.awt.event.FocusAdapter()
            {
               @Override
                public void focusGained( FocusEvent e )
                {
                    // TODO Auto-generated method stub
                    super.focusGained(e);
                    SwingUtilities.invokeLater(new Runnable() {
                        
                        @Override
                        public void run()
                        {
                            currentTextField.selectAll();
                        }
                    });
                } 
            });
            
            qBinsPanel.add( quantizationLabels[i]);
            qBinsPanel.add( quantizationParameters[i]);
        }
        

        // Select the first button of all the button groups
        colorspaceButtons[0].setSelected(true);
        predictiveCodingButtons[0].setSelected(true);
        quantizationButtons[0].setSelected(true);
        encodingButtons[0].setSelected(true);
        phase2Frame.getContentPane().setLayout(null);

        JPanel browsePanel = new JPanel();
        browsePanel.setBounds(0, 0, 727, 43);
        phase2Frame.getContentPane().add(browsePanel);

        pathTextField = new JTextField();
        pathTextField.setColumns(10);

        browseButton = new JButton("Browse...");
        browseButton.setActionCommand("browseButton");
        GroupLayout gl_browsePanel = new GroupLayout(browsePanel);
        gl_browsePanel.setHorizontalGroup(gl_browsePanel.createParallelGroup(Alignment.TRAILING).addGroup(
                Alignment.LEADING,
                gl_browsePanel.createSequentialGroup().addContainerGap()
                        .addComponent(pathTextField, GroupLayout.DEFAULT_SIZE, 595, Short.MAX_VALUE)
                        .addPreferredGap(ComponentPlacement.RELATED).addComponent(browseButton).addContainerGap()));
        gl_browsePanel.setVerticalGroup(gl_browsePanel.createParallelGroup(Alignment.LEADING).addGroup(
                gl_browsePanel
                        .createSequentialGroup()
                        .addContainerGap()
                        .addGroup(
                                gl_browsePanel
                                        .createParallelGroup(Alignment.BASELINE)
                                        .addComponent(pathTextField, GroupLayout.PREFERRED_SIZE, 25,
                                                GroupLayout.PREFERRED_SIZE).addComponent(browseButton))
                        .addContainerGap(233, Short.MAX_VALUE)));
        browsePanel.setLayout(gl_browsePanel);

        codingTabbedPane = new JTabbedPane(JTabbedPane.TOP);
        codingTabbedPane.setBounds(0, 43, 727, 221);
        phase2Frame.getContentPane().add(codingTabbedPane);

        JPanel encodingTabPanel = new JPanel();
        codingTabbedPane.addTab("Encoding", null, encodingTabPanel, null);

        generateFileButton = new JButton("Generate Binary File");
        generateFileButton.setActionCommand("encodeButton");

        encodingPanel.setLayout(new GridLayout(4, 1, 0, 0));
        encodingPanel.add(encodingButtons[0]);
        encodingPanel.setBorder(BorderFactory.createTitledBorder("Encoding"));

        predictiveCodingPanel.setLayout(new GridLayout(5, 2, 0, 0));
        predictiveCodingPanel.add(predictiveCodingButtons[0]);

        predictiveCodingPanel.setBorder(BorderFactory.createTitledBorder("Predictive Coding"));

        quantizationPanel.setLayout(new GridLayout(3, 1, 0, 0));
        quantizationPanel.add(quantizationButtons[0]);
        quantizationPanel.setBorder(BorderFactory.createTitledBorder("Quantization"));
        JPanel colorspacePanel = new JPanel();

        colorspacePanel.setLayout(new GridLayout(2, 1, 0, 0));

        colorspacePanel.add(colorspaceButtons[0]);
        colorspacePanel.add(colorspaceButtons[1]);
        colorspacePanel.setBorder(BorderFactory.createTitledBorder("Colorspace"));
        
        
        qBinsPanel.setBorder(new TitledBorder(new LineBorder(new Color(184, 207, 229)), "Bins", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(51, 51, 51)));
        GroupLayout gl_encodingTabPanel = new GroupLayout(encodingTabPanel);
        gl_encodingTabPanel.setHorizontalGroup(
            gl_encodingTabPanel.createParallelGroup(Alignment.LEADING)
                .addGroup(Alignment.TRAILING, gl_encodingTabPanel.createSequentialGroup()
                    .addContainerGap(16, Short.MAX_VALUE)
                    .addComponent(colorspacePanel, GroupLayout.PREFERRED_SIZE, 98, GroupLayout.PREFERRED_SIZE)
                    .addGap(10)
                    .addComponent(quantizationPanel, GroupLayout.PREFERRED_SIZE, 159, GroupLayout.PREFERRED_SIZE)
                    .addGap(10)
                    .addComponent(qBinsPanel, GroupLayout.PREFERRED_SIZE, 102, GroupLayout.PREFERRED_SIZE)
                    .addGap(10)
                    .addComponent(predictiveCodingPanel, GroupLayout.PREFERRED_SIZE, 150, GroupLayout.PREFERRED_SIZE)
                    .addGap(10)
                    .addComponent(encodingPanel, GroupLayout.PREFERRED_SIZE, 141, GroupLayout.PREFERRED_SIZE)
                    .addGap(16))
                .addGroup(gl_encodingTabPanel.createSequentialGroup()
                    .addGap(258)
                    .addComponent(generateFileButton)
                    .addContainerGap(285, Short.MAX_VALUE))
        );
        gl_encodingTabPanel.setVerticalGroup(
            gl_encodingTabPanel.createParallelGroup(Alignment.LEADING)
                .addGroup(Alignment.TRAILING, gl_encodingTabPanel.createSequentialGroup()
                    .addContainerGap(14, Short.MAX_VALUE)
                    .addGroup(gl_encodingTabPanel.createParallelGroup(Alignment.LEADING, false)
                        .addGroup(gl_encodingTabPanel.createParallelGroup(Alignment.BASELINE)
                            .addComponent(colorspacePanel, GroupLayout.DEFAULT_SIZE, 137, Short.MAX_VALUE)
                            .addComponent(quantizationPanel, GroupLayout.DEFAULT_SIZE, 137, Short.MAX_VALUE))
                        .addGroup(gl_encodingTabPanel.createParallelGroup(Alignment.BASELINE)
                            .addComponent(qBinsPanel, GroupLayout.PREFERRED_SIZE, 137, GroupLayout.PREFERRED_SIZE)
                            .addComponent(encodingPanel, GroupLayout.DEFAULT_SIZE, 137, Short.MAX_VALUE)
                            .addComponent(predictiveCodingPanel, GroupLayout.DEFAULT_SIZE, 137, Short.MAX_VALUE)))
                    .addPreferredGap(ComponentPlacement.RELATED)
                    .addComponent(generateFileButton)
                    .addContainerGap())
        );
        qBinsPanel.setLayout(new GridLayout(4, 2, 0, 0));
        encodingTabPanel.setLayout(gl_encodingTabPanel);
        
        JPanel decodingTabPanel = new JPanel();
        codingTabbedPane.addTab("Decoding", null, decodingTabPanel, null);
        
        decodeFileButton = new JButton("Decode Binary File");
        decodeFileButton.setActionCommand("decodeButton");
        GroupLayout gl_decodingTabPanel = new GroupLayout(decodingTabPanel);
        gl_decodingTabPanel.setHorizontalGroup(
            gl_decodingTabPanel.createParallelGroup(Alignment.LEADING)
                .addGroup(Alignment.TRAILING, gl_decodingTabPanel.createSequentialGroup()
                    .addContainerGap(288, Short.MAX_VALUE)
                    .addComponent(decodeFileButton)
                    .addGap(269))
        );
        gl_decodingTabPanel.setVerticalGroup(
            gl_decodingTabPanel.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_decodingTabPanel.createSequentialGroup()
                    .addGap(81)
                    .addComponent(decodeFileButton)
                    .addContainerGap(88, Short.MAX_VALUE))
        );
        decodingTabPanel.setLayout(gl_decodingTabPanel);
        
        JPanel distortionCalcPanel = new JPanel();
        codingTabbedPane.addTab("Distortion", null, distortionCalcPanel, null);
        
        distortedFileField = new JTextField();
        distortedFileField.setColumns(10);
        
        distortedBrowseButton = new JButton("Browse...");
        
        calculateDistortionButton = new JButton("Calculate Distortion");
        
        distortionLabel = new JLabel("0");
        distortionLabel.setHorizontalAlignment(SwingConstants.CENTER);
        GroupLayout gl_distortionCalcPanel = new GroupLayout(distortionCalcPanel);
        gl_distortionCalcPanel.setHorizontalGroup(
            gl_distortionCalcPanel.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_distortionCalcPanel.createSequentialGroup()
                    .addGroup(gl_distortionCalcPanel.createParallelGroup(Alignment.LEADING, false)
                        .addGroup(gl_distortionCalcPanel.createSequentialGroup()
                            .addGap(274)
                            .addComponent(calculateDistortionButton)
                            .addGap(266))
                        .addGroup(gl_distortionCalcPanel.createSequentialGroup()
                            .addContainerGap()
                            .addComponent(distortedFileField, GroupLayout.PREFERRED_SIZE, 595, GroupLayout.PREFERRED_SIZE)
                            .addPreferredGap(ComponentPlacement.RELATED)
                            .addComponent(distortedBrowseButton, GroupLayout.PREFERRED_SIZE, 102, GroupLayout.PREFERRED_SIZE)))
                    .addGap(7))
                .addGroup(gl_distortionCalcPanel.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(distortionLabel, GroupLayout.DEFAULT_SIZE, 704, Short.MAX_VALUE)
                    .addContainerGap())
        );
        gl_distortionCalcPanel.setVerticalGroup(
            gl_distortionCalcPanel.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_distortionCalcPanel.createSequentialGroup()
                    .addGap(26)
                    .addGroup(gl_distortionCalcPanel.createParallelGroup(Alignment.BASELINE)
                        .addComponent(distortedFileField, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)
                        .addComponent(distortedBrowseButton))
                    .addPreferredGap(ComponentPlacement.UNRELATED)
                    .addComponent(calculateDistortionButton)
                    .addGap(30)
                    .addComponent(distortionLabel)
                    .addContainerGap(61, Short.MAX_VALUE))
        );
        distortionCalcPanel.setLayout(gl_distortionCalcPanel);
    }

    /**
     * @return the predictiveCodingButtonGroup
     */
    public ButtonGroup getPredictiveCodingButtonGroup()
    {
        return predictiveCodingButtonGroup;
    }

    /**
     * @return the quantizationButtonGroup
     */
    public ButtonGroup getQuantizationButtonGroup()
    {
        return quantizationButtonGroup;
    }

    /**
     * @return the encodingButtonGroup
     */
    public ButtonGroup getEncodingButtonGroup()
    {
        return encodingButtonGroup;
    }

    /**
     * @return the colorspaceButtonGroup
     */
    public ButtonGroup getColorspaceButtonGroup()
    {
        return colorspaceButtonGroup;
    }

    /**
     * @return the pathTextField
     */
    public JTextField getPathTextField()
    {
        return pathTextField;
    }

    /**
     * @param pathTextField
     *            the pathTextField to set
     */
    public void setPathTextField( JTextField pathTextField )
    {
        this.pathTextField = pathTextField;
    }

    /**
     * @return the codingTabbedPane
     */
    public JTabbedPane getCodingTabbedPane()
    {
        return codingTabbedPane;
    }

    /**
     * @return the quantizationParameters
     */
    public JTextField[] getQuantizationParameters()
    {
        return quantizationParameters;
    }

    /**
     * @param quantizationParameters the quantizationParameters to set
     */
    public void setQuantizationParameters( JTextField[] quantizationParameters )
    {
        this.quantizationParameters = quantizationParameters;
    }

    public JTextField getDistortedFileField()
    {
        return distortedFileField;
    }

    public void setDistortedFileField( JTextField distortedFileField )
    {
        this.distortedFileField = distortedFileField;
    }

    public void setDistortionLabel( JLabel distortionLabel )
    {
        this.distortionLabel = distortionLabel;
    }

    public JLabel getDistortionLabel()
    {
        return distortionLabel;
    }

    public void setGenerateFileButtonListener( ActionListener listener )
    {
        generateFileButton.addActionListener(listener);
    }
    
    public void setDecodeFileButtonListener( ActionListener listener )
    {
        decodeFileButton.addActionListener(listener);
    }
    
    public void setDistortionButtonListener( ActionListener listener )
    {
        calculateDistortionButton.addActionListener(listener);
    }
    
    private JButton calculateDistortionButton;

    public void setBrowseButtonListener( ActionListener listener )
    {
        browseButton.addActionListener(listener);
        distortedBrowseButton.addActionListener(listener);
    }
}
